package fpzhan.plane.program.proxy;

import com.alibaba.fastjson.JSONObject;
import fpzhan.plane.program.compose.ComposeContext;
import fpzhan.plane.program.constant.FlowDefine;
import fpzhan.plane.program.exception.*;
import fpzhan.plane.program.manager.JsonKeyManager;
import fpzhan.plane.program.compose.ComposeContent;
import fpzhan.plane.program.util.SetUtils;

import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

public class CheckParamProxy extends CodeBlockProxy{

    public CheckParamProxy(String proxyName ) {
        super(proxyName, 0);
    }

    @Override
    public JSONObject before(ComposeContext composeContext, ComposeContent composeContent, Set<String> keys, JSONObject json) throws Exception {
        json.put(JsonKeyManager.getJsonKey().beforeRunParamsKey,keys);
        return json;
    }

    @Override
    public void after(JSONObject before, ComposeContext composeContext,ComposeContent composeContent, Set<String> keys ,   JSONObject json) throws Exception {
        Set<String> beforeKeys = (Set<String> ) before.get(JsonKeyManager.getJsonKey().beforeRunParamsKey);
        json.put(JsonKeyManager.getJsonKey().beforeRunParamsKey,beforeKeys.toString());
        json.put(JsonKeyManager.getJsonKey().afterParamsKey,keys.toString());
        compare(new HashSet<>(beforeKeys),new HashSet<>(keys), composeContext.getLoses(), composeContext.getAdds());

    }

    private  void compare(Set<String> beforeKeys,Set<String> afterKeys,String [] lose ,String [] add) throws FlowException {
        List same = afterKeys.stream().filter(beforeKeys::contains).collect(Collectors.toList());
        afterKeys.removeAll(same);
        beforeKeys.removeAll(same);
        Set<String> loses=(lose==null?new HashSet<>():new HashSet<>(Arrays.asList(lose)));
        Set<String> adds=(add==null?new HashSet<>():new HashSet<>(Arrays.asList(add)));
        loses.removeAll(same);
        adds.removeAll(same);
        int loseValue = SetUtils.compare(beforeKeys,loses);
        switch (loseValue){
            case FlowDefine.LOSE:
            case FlowDefine.MORE:
                throw new CheckLoseParamLengthException(beforeKeys.size(), loses.size());
            case FlowDefine.FALSE:
                throw new CheckLoseParamException(beforeKeys,loses);
        }
        int addValue = SetUtils.compare(afterKeys,adds);
        switch (addValue){
            case FlowDefine.LOSE:
            case FlowDefine.MORE:
                throw new CheckAddParamLengthException(afterKeys.size(),adds.size());
            case FlowDefine.FALSE:
                throw new CheckAddParamException(afterKeys,adds);
        }

    }
}
